/**
 * ---------------------------
 * Time: 2017/5/12 20:51.
 * Author: Cangshi
 * View: http://palerock.cn
 * ---------------------------
 */
/**
 * CanvasInnerObject canvas内部需要被绘画的对象
 * @param config 配置参数
 * {
 *
 * }
 */
var CanvasInnerObject = Main.createConfigClass({
    default: {
        defaultVar: function () {
            return this.doSuper('defaultVar', arguments)
                .extend({
                    runningTrack: null
                }, true);
        },
        defaultConfig: function () {
            return this.doSuper('defaultConfig', arguments)
                .extend({
                    name: 'CanvasInnerObject',
                    canvasModel: {
                        size: 0.25
                    }
                }, true);
        },
        onConfigured: function () {
            this.doSuper('onConfigured', arguments);
            this._configTrack();
            this._configModel();
        },
        _configTrack: function () {
            this.runningTrack = {
                parent: this
            };
            this.runningTrack.__proto__ = RunningTrack.prototype;
            RunningTrack.call(this.runningTrack, this.config.runningTrack);
        },
        _configModel: function () {
            this.canvasModel = {
                parent: this
            };
            this.canvasModel.__proto__ = CanvasModel.prototype;
            RunningTrack.call(this.canvasModel, this.config.canvasModel);
        }
    },
    defaultPrototype: {
        showName: function () {
            console.log('CanvasInnerObject:');
            this.doSuper('showName', arguments);
        },
        getDrawConfig: function () {
            var config = this.canvasModel.getResultConfig();
            config.expand(this.runningTrack.getCurrentPoint());
            return config;
        },
        getModelRadius: function () {
            return {
                wR: this.canvasModel.realWidth / 2,
                hR: this.canvasModel.realHeight / 2
            }
        },
        run: function () {
            // 执行默认轨迹更新
            this.runningTrack.runningStart();
            // 检查模型的渲染队列，并执行特效更新
            var modelThis = this.canvasModel;
            // 添加默认的渲染队列
            if (modelThis.hasEffect('running')) {
                modelThis.addEffectInService('running');
            }
            modelThis.effectMap.map(function (key) {
                if (modelThis.hasEffectInService(key)) {
                    modelThis.playEffect(key);
                }
            });
        },
        stop: function () {
            this.runningTrack.runningEnd();
            var modelThis = this.canvasModel;
            modelThis.effectMap.map(function (key) {
                if (modelThis.hasEffectInService(key)) {
                    modelThis.pauseEffect(key);
                }
            });
        }
    },
    parentClass: {
        class: GameObject,
        args: []
    }
});

var Canvas = Main.createConfigClass({
    default: {
        defaultVar: function () {
            return {
                objMap: {},
                status: this.BIRTH
            }
        },
        defaultConfig: function () {
            return {
                objType: CanvasInnerObject
            }
        },
        onConfigured: function () {
            if (!this.config.el) {
                throw new Error('未指定画布对象');
            }
            this.canvas = document.getElementById(this.config.el);
            if (!this.canvas) {
                throw new Error('找不到指定画布');
            }
            this.matchParentSpace();
            this.ctx = this.canvas.getContext('2d');
            this.objType = this.config.objType;
        }
    },
    defaultPrototype: {
        matchParentSpace: function () {
            // 设置canvas的长宽
            var parent = this.canvas.parentNode;
            var width = parent.offsetWidth;
            var height = parent.offsetHeight;
            this.canvas.width = width;
            this.canvas.height = height;
        },
        addObject: function (obj) {
            if (!(obj instanceof this.objType)) {
                throw new Error('欲添加画布内容的对象类型不正确');
            }
            this.objMap[obj.id] = obj;
            if (obj.children) {
                var _this = this;
                obj.children.map(function (key) {
                    _this.addObject(this[key]);
                })
            }
        },
        removeObject: function (id) {
            delete this.objMap[id];
        },
        startDraw: function () {
            this.objMap.map(function (key) {
                // 执行默认更新
                this[key].run();
            });
            this.status = this.RUNNING;
            this.drawAll();
        },
        stopDraw: function () {
            this.status = this.BIRTH;
            this.objMap.map(function (key) {
                // 关闭所有更新
                this[key].stop();
            });
        },
        rotatePoint: function (x, y, deg, callback) {
            var ctx = this.ctx;
            ctx.save();
            ctx.translate(x, y);
            ctx.rotate(deg * Math.PI / 180);//旋转
            ctx.translate(-x, -y);
            callback.call(this, ctx);
            ctx.restore();
        },
        drawImg: function (config) {
            this.rotatePoint(
                config.x + config.width / 2,
                config.y + config.height / 2,
                config.deg,
                function (ctx) {
                    ctx.drawImage(config.img, config.x, config.y, config.width, config.height);
                });
        },
        drawRect: function (config) {
            this.rotatePoint(
                config.x + config.width / 2,
                config.y + config.height / 2,
                config.deg,
                function (ctx) {
                    ctx.fillStyle = config.color;
                    ctx.fillRect(config.x, config.y, config.width, config.height);
                });
        },
        drawEffect: function (effect) {
            var effectConfig = effect.getDrawConfig();
            var _this = this;
            switch (effectConfig.type) {
                case 'particles':
                    effect.particles.particleList.listArray(function (i) {
                        _this.drawEffect(this[i]);
                    });
                    break;
                case 'simple':
                    effectConfig.x = effectConfig.x - effectConfig.width / 2;
                    effectConfig.y = effectConfig.y - effectConfig.height / 2;
                    // 判断是否跟随切换对象角度
                    if (effectConfig.isFaceDeg) {
                        effect.effect.degFaced = effectConfig.runningTrack.deg;
                    } else if (effectConfig.rotate.isRotate) {
                        effect.effect.degFaced = effect.effect.degFaced + effectConfig.rotate.frameDeg;
                        effect.effect.degFaced %= 360;
                    }
                    effectConfig.deg = effect.effect.degFaced;
                    switch (effectConfig.effect.type) {
                        default:
                        case 'rect':
                            this.drawRect(effectConfig);
                            break;
                    }
                    break;
                default:
                    break;
            }
        },
        drawModel: function (obj) {
            if (!obj.canvasModel.isReady) {
                return;
            }
            var config = obj.getDrawConfig();
            if (!(config.x && config.y && config.width && config.height)) {
                return;
            }
            var modelRadius = obj.getModelRadius();

            config.x = config.x - modelRadius.wR;
            config.y = config.y - modelRadius.hR;

            // 判断是否跟随切换对象角度
            if (config.isFaceDeg) {
                obj.canvasModel.degFaced = config.runningTrack.deg;
            } else if (config.rotate.isRotate) {
                obj.canvasModel.degFaced = obj.canvasModel.degFaced + config.rotate.frameDeg;
                obj.canvasModel.degFaced %= 360;
            }
            config.deg = obj.canvasModel.degFaced;
            switch (config.type) {
                case 'image':
                    if (!config.img) {
                        return;
                    }
                    this.drawImg(config);
                    break;
                case 'rect':
                    this.drawRect(config);
                    break;
                default:
                    break;
            }
        },
        draw: function (obj) {
            if (!(obj instanceof this.objType)) {
                throw new Error('该对象不能由画布渲染');
            }

            // 检查当前模型中特效渲染队列，并执行渲染
            var _this = this;
            var model = obj.canvasModel;
            model.effectMap.map(function (key) {
                if (model.hasEffectInService(key))
                    _this.drawEffect(model.effectMap[key]);
            });

            // 渲染模型本身
            this.drawModel(obj);
        },
        drawAll: function () {
            this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
            if (this.status == this.RUNNING) {
                var _this = this;
                this.objMap.map(function (key) {
                    _this.draw(_this.objMap[key]);
                });
                requestAnimationFrame(function () {
                    _this.drawAll();
                });
            }
        }
    }
});